/*
Copyright (C) 2008 raohmaru <http://www.raohmaru.com>

This file is part of Raohmaru AS3 Framework.

Raohmaru AS3 Framework is free software: you can redistribute it and/or modify
it under the terms of the GNU Lesser General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.

Raohmaru AS3 Framework is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
GNU Lesser General Public License for more details.

You should have received a copy of the GNU Lesser General Public License
along with Raohmaru AS3 Framework.  If not, see <http://www.gnu.org/licenses/>.
*/

package jp.raohmaru.system.core
{
import jp.raohmaru.system.data.ExternalData;

import flash.events.*;
import flash.events.EventDispatcher;

/**
 * Se distribuye cuando todos los datos de la lista se han cargado, correctamente o no.
 * @eventType flash.events.Event.COMPLETE
 */
[Event(name="complete", type="flash.events.Event") ]

/**
 * Se distribuye cuando se produce un error en la carga de una fuente de datos. La fuente del error se omite y se pasa al siguiente archivo de datos a cargar.
 * @eventType flash.events.IOErrorEvent.IO_ERROR
 */
[Event(name="ioError", type="flash.events.IOErrorEvent") ]

/**
 * Se distribuye al recibirse datos mientras progresa una operación de descarga.
 * @eventType flash.events.ProgressEvent.PROGRESS
 */
[Event(name="progress", type="flash.events.ProgressEvent") ]

/**
 * La clase Setup es un objeto de ayuda para cargar datos externos procesados en cola. Muy útil para la carga de configuraciones iniciales de la aplicación.
 * Para el proceso de carga se utiliza la clase ExternalData.
 * @example
<listing version="3.0">
import jp.raohmaru.system.core.Setup;
import flash.events.Event;
var _setup :Setup = new Setup();
    _setup.addData("config", "config.xml");    _setup.addData("score", "php/get_score.php");
    _setup.addEventListener(Event.COMPLETE, onSetupComplete);
    _setup.init()
function onSetupComplete(e :Event) : void
{
    var data :XML = new XML(_setup.config);  // Los datos se almacenan en el objeto Setup con el nombre definido en Setup.addData() 
}
</listing>
 * @see jp.raohmaru.system.data.ExternalData
 * @author raohmaru
 * @version 1.1
 */
public dynamic class Setup extends EventDispatcher
{
	private var _datas : Array = [],
				_data_ind : uint,
				_current_data :ExternalData;
	
	/**
	 * Obtiene el progreso de la descarga (0 -> nada descargado, 1 -> 100% descargado)
	 */
	public function get loaded() :Number
	{
		return (1/_datas.length)*_data_ind;
	}
	
	/**
	 * Crea una nueva instancia de Setup.
	 */
	public function Setup()
	{
	}
	
	/**
	 * Añade una nueva fuente de datos a la lista de carga.
	 * @param name Nombre de la fuente de datos. Una vez cargada servirá para acceder al objeto XML con los datos.
	 * @param url URL de la fuente de datos.
	 */
	public function addData(name :String, url :String) :void
	{
		_datas.push([name, url]);
	}

	/**
	 * Inicia el proceso de carga. Es necesario invocarlo explícitamente.
	 */
	public function init() : void
	{
		loadNextData();
	}

	private function loadNextData() : void
	{
		if(_data_ind < _datas.length)
		{
			_current_data = new ExternalData();
			_current_data.addEventListener(Event.COMPLETE, onLoadData);
			_current_data.addEventListener(IOErrorEvent.IO_ERROR, onLoadData);
			_current_data.addEventListener(ProgressEvent.PROGRESS, onProgress);
			_current_data.load(_datas[_data_ind][1]);
		}
		else
		{
			dispatchEvent(new Event(Event.COMPLETE));
		}
	}

	private function onLoadData(e : Event) : void
	{
		e.target.removeEventListener(Event.COMPLETE, onLoadData);
		e.target.removeEventListener(IOErrorEvent.IO_ERROR, onLoadData);
		e.target.removeEventListener(ProgressEvent.PROGRESS, onProgress);

		if(e.type == Event.COMPLETE)
			this[_datas[_data_ind][0]] = e.target.data;
		
		else
			dispatchEvent(e);
		
		_data_ind++;
		loadNextData();
	}
	
	private function onProgress(e :ProgressEvent) : void
	{
		dispatchEvent(e);
	}
}
}